package com.zlc.common.common.service;

import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlc.common.aop.PersistenceAop;
import com.zlc.common.common.entity.BaseEntity;
import com.zlc.common.common.exception.BusinessException;
import com.zlc.common.util.BeanCopyUtils;
import com.zlc.common.util.JsonHelper;
import com.zlc.common.util.wrapper.SqlHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class BaseServiceImpl<M extends BaseMapper<T>,T extends BaseEntity,V extends BaseEntity > extends ServiceImpl<M,T>
        implements BaseService<M,T,V>{

    /**
     * 实体类Vo
     */
    private final Class<V> entityVoClass;
    /***
     * 实体类
     */
    private final Class<T> entityClass;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    public BaseServiceImpl() {
        Type[] types = ((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments();
        this.entityVoClass = (Class<V>)types[2];
        this.entityClass = (Class<T>)types[1];
    }


    @Override
    protected Class<T> currentMapperClass() {
        return (Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    @Override
    protected Class<T> currentModelClass() {
        return (Class)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
    }

    @Override
    public List<V> queryVoList(LambdaQueryWrapper<T> wrapper){
        List<T> list = this.list(wrapper);
        if(!ObjectUtils.isEmpty(list)){
            return BeanCopyUtils.copyObjList(list,entityVoClass);
        }
        return new ArrayList<>();
    }

    @Override
    public V queryOne(LambdaQueryWrapper<T> wrapper) {
        List<V> list = this.queryVoList(wrapper);
        if(!ObjectUtils.isEmpty(list)){
            return list.get(0);
        }
        return null;
    }

    @Override
    public V queryOne(String id) {
        T t = baseMapper.selectById(id);
        return BeanCopyUtils.copyObj(t,entityVoClass);
    }

    @Override
    public V saveVo(V vo) {
        PersistenceAop.addField(vo);
        if(vo.getId() != null){
            String id = vo.getId();
            T t = baseMapper.selectById(id);
            T e = BeanCopyUtils.copyObj(vo,entityClass);
            if(ObjectUtils.isEmpty(t)){
                super.save(e);
                e.setVersion(0);
                return BeanCopyUtils.copyObj(e,entityVoClass);
            }else{
                boolean ret = super.updateById(e);
                if(!ret){
                    throw new BusinessException("数据已经被修改，请刷新后重试！");
                }
                return BeanCopyUtils.copyObj(e,entityVoClass);
            }
        }else {
            T e = BeanCopyUtils.copyObj(vo, entityClass);
            super.save(e);
            return BeanCopyUtils.copyObj(e, entityVoClass);
        }
    }

    @Override
    public int deleteById(String id) {
        return baseMapper.deleteById(id);
    }

    @Override
    public void deleteObjById(String id) {
        String tableName = JsonHelper.toUnderLineField(JsonHelper.firstLowerValue(entityClass.getSimpleName()));
        TableName annotation = entityClass.getAnnotation(TableName.class);
        if(!ObjectUtils.isEmpty(annotation)){
            tableName = annotation.value();
        }
        jdbcTemplate.execute("delete from "+tableName+" where id_ = '"+id+"' ");
    }

    @Override
    public void deleteObjByIds(List<String> ids) {
        String tableName = JsonHelper.toUnderLineField(JsonHelper.firstLowerValue(entityClass.getSimpleName()));
        TableName annotation = entityClass.getAnnotation(TableName.class);
        if(!ObjectUtils.isEmpty(annotation)){
            tableName = annotation.value();
        }
        String sql = "delete from "+tableName+" where id_ in " + SqlHelper.inStr(ids);
        jdbcTemplate.execute(sql);
    }

    @Override
    public List<V> saveVoList(List<V> vos) {
        List<V> result = new ArrayList<>();
        for(V vo : vos){
            result.add(saveVo(vo));
        }
        return result;
    }

    @Override
    public List<V> saveBatchVoList(List<V> vos) {
        //分批
        List<V> addList = vos.stream().filter(v -> ObjectUtils.isEmpty(v.getId())).collect(Collectors.toList());
        List<V> updateList = vos.stream().filter(v -> !ObjectUtils.isEmpty(v.getId())).collect(Collectors.toList());
        if(!ObjectUtils.isEmpty(addList)){
            addList.forEach(PersistenceAop::addField);
            List<T> addListT = BeanCopyUtils.copyObjList(addList,entityClass);
            super.saveBatch(addListT,1000);
        }
        if(!ObjectUtils.isEmpty(updateList)){
            updateList.forEach(PersistenceAop::addField);
            List<T> updateListT = BeanCopyUtils.copyObjList(updateList,entityClass);
            super.updateBatchById(updateListT,1000);
        }
        return vos;
    }

    @Override
    public LambdaQueryWrapper<T> wrapper(){
        return new LambdaQueryWrapper<T>();
    }


}

